<template>
	<view class="video-device-form">
		<!-- <view class="header"> -->
		<!-- <img src="../../static/arrow.png" alt="" class="back-img" /> -->
		<!-- <text class="header-title">视频调试</text> -->
		<!-- </view> -->
		<!-- 边设备信息 -->
		<view class="video-device-container">
			<view class="form-header">
				<view class="flex-alin">
					<text class="header-text">NVR信息</text>
					<view class="header-tag">
						<uni-tag text="在线" type="success"></uni-tag>
					</view>
				</view>

			</view>

			<view class="video-device-info">

				<view class="form-row">
					<!-- 设备名称 -->
					<uni-forms-item label="设备名称" required name="name" class="info-item" label-width=60>
						<uni-easyinput disabled v-model="nvr.name" placeholder="请输入设备名称" />
					</uni-forms-item>


				</view>
				<view class="form-row">
					<uni-forms-item label="前端编码" required name="frontCode" class="info-item" label-width=60>
						<uni-data-select @change="selectFrontCode()" :localdata="codeOptions" v-model="tzObj.frontCode"
							placeholder="请选择前端编码" />
					</uni-forms-item>
				</view>


			</view>
		</view>

		<uni-popup style="width: 600px;" ref="editDialog" type="dialog">
			<uni-popup-dialog style="width: 600px;" title="摄像机信息" :before-close="true" @close="closeEdit()"
				@confirm="saveEdit()">
				<!-- :rules="rules"  -->
				<uni-forms style="width: 550px;" ref="editRef" :modelValue="editForm" class="form-container-box">
					<uni-forms-item label-width="80px" label="通道号" required name="channel" class="info-item">
						<uni-easyinput disabled :clearable="false" v-model="editForm.channel" placeholder="请输入序列号" />
					</uni-forms-item>
					<uni-forms-item label-width="80px" label="通道名称" required name="name" class="info-item">
						<uni-easyinput disabled :clearable="false" v-model="editForm.name" placeholder="请输入密码" />
					</uni-forms-item>
					<uni-forms-item label-width="80px" label="设备类型" required name="type" class="info-item">
						<uni-easyinput disabled :clearable="false" v-model="editForm.type" placeholder="请输入ip" />
					</uni-forms-item>
					<uni-forms-item label-width="80px" label="ip" required name="ip" class="info-item">
						<uni-easyinput disabled :clearable="false" v-model="editForm.ip" placeholder="请输入掩码" />
					</uni-forms-item>
					<uni-forms-item label-width="80px" label="设备编码" required name="sgcode" class="info-item">
						<uni-data-select v-model="editForm.sgcode" :localdata="sgcodeOption"
							placeholder="请选择您要修改的设备编码" />
					</uni-forms-item>
				</uni-forms>

			</uni-popup-dialog>
		</uni-popup>

		<!-- 视频设备列表 -->
		<view class="video-device-list-container">
			<view class="video-device-list-header">
				<text class="video-device-list-title">视频设备列表</text>
			</view>

			<uni-table ref="table" :loading="loading" border stripe type="selection" emptyText="暂无更多数据"
				@selection-change="selectionChange">
				<uni-tr>
					<uni-th width="100" align="center">通道号</uni-th>
					<uni-th width="120" align="center">通道名称</uni-th>
					<uni-th width="120" align="center">设备类型</uni-th>
					<uni-th width="100" align="center">设备编码</uni-th>
					<uni-th width="100" align="center">IP地址</uni-th>
					<uni-th width="90" align="center">状态</uni-th>
					<uni-th width="200" align="center">操作</uni-th>
				</uni-tr>
				<uni-tr v-for="(item, index) in cameraTable" :key="index">
					<uni-td align="center">{{ item.channel }}</uni-td>
					<uni-td align="center">{{ item.name }}</uni-td>
					<uni-td align="center">
						<view v-if="item.type==='box'">枪机</view>
						<view v-if="item.type==='dome'">球机</view>
					</uni-td>
					<uni-td align="center">{{ item.sgcode }}</uni-td>
					<uni-td align="center">{{ item.ip }}</uni-td>
					<uni-td align="center">
						<uni-tag v-if="item.channel && item.state=== 1" text="在线" type="success"></uni-tag>
						<uni-tag v-if="item.channel && item.state=== 2" text="离线" type="warning"></uni-tag>
						<uni-tag v-if="!item.channel" text="未分配" type="default"></uni-tag>
					</uni-td>
					<uni-td align="center">
						<button style="margin-right: 3px;" size="mini" type="default"
							@click="editCamera(item)">编辑</button>
						<button v-if="item.channel" size="mini" type="default" @click="videoPreview(item)">查看</button>
					</uni-td>
				</uni-tr>

			</uni-table>

		</view>


		<!-- 底部 -->
		<view class="button-bar">
			<button type="primary" class="add-channel-btn" @click="importExcel()">
				<view class="icon-container">
					<image src="../../static/lu_05.png" mode="" class="icon"></image>
				</view>导入平台台账
			</button>
			<!-- <button type="primary" class="import-btn">导入平台台账</button> -->
			<button type="primary" class="save-btn-video" @click="save()">
				<view class="icon-container">
					<image src="../../static/check.png" mode="" class="icon"></image>
				</view>保存设置
			</button>
		</view>
	</view>
</template>

<script setup lang="ts">
	import { ref, onMounted, reactive } from 'vue'
	import * as XLSX from 'xlsx';
	import { WEB_URL } from '../../config/global';
	import { getJsonData } from '../../js_sdk/file';
	import {
		onLoad
	} from '@dcloudio/uni-app';
	const videoDeviceList = ref()
	const deviceFind = ref()
	const inputDialog = ref()
	const station = ref()
	const tzObj = ref({
		frontCode: '',
		deviceCode: ''
	})
	const platformData = ref()
	const editRef = ref()
	const cameraTable = ref([])
	const sgcodeOption = ref([])
	const sgcodeOptionBak = ref([])
	const waitChannelList = ref([])
	const activated = ref()
	const deviceForm = ref();
	const editForm = ref({
		ip: "",
		channel: 0,
		name: "",
		sgcode: "",
		type: ""
	})
	const serial = ref()
	const editDialog = ref()
	const loading = ref(true)
	const disk = ref({})
	const nvr = ref({

	})
	const formData = reactive({
		password: "",
		user: "",
		ip: "",
		port: "",
		manual: "1"
	})
	const selectedIndexs = ref([]);
	const codeOptions = ref([]);
	const tzArray = ref([]);

	//设备发现中的camera
	const cameraFromFind = ref([]);
	//通道信息中的camera
	const cameraFromChannel = ref([]);
	//设备列表中的camera
	const cameraFromDeivce = ref([]);

	const rules = {
		ip: {
			rules: [{
				required: true,
				errorMessage: 'ip不能为空'
			}]
		},
		port: {
			rules: [{
				required: true,
				errorMessage: '端口不能为空'
			}]
		},
		user: {
			rules: [{
				required: true,
				errorMessage: '用户名不能为空'
			}]
		},
		password: {
			rules: [{
				required: true,
				errorMessage: '密码不能为空'
			}]
		}
	};

	onLoad(async (options) => {
		if (!Object.keys(options).length == 0) {
			station.value = JSON.parse(decodeURIComponent(options.item))
		}

		let filePath2 = '_doc/test/platform.json'
		let dataJson2 = await getJsonData(filePath2)
		if (dataJson2 === '') {
		} else {
			platformData.value = JSON.parse(dataJson2);
		}

		// station.value = {
		// 	videoData: {
		// 		videoPort: 8000,
		// 		videoUsername: "admin",
		// 		videoPassword: "njzt12345"
		// 	}
		// }
		// nvr.value.ip = "192.168.1.155"

		uni.showLoading({
			title: '数据加载中'
		});
		//读取默认配置
		//1.获取设备列表 
		await getDeviveList()
		//2.默认调用一次设备发现
		await find()
		//4.初始化通道信息
		await getChannelInfo()
		initTableData()
	})

	const saveEdit = () => {
		// console.log('editForm', editForm.value);
		let camera = cameraTable.value.find(function (item) {
			return item.channel === editForm.value.channel
		})
		camera.sgcode = editForm.value.sgcode
		editDialog.value.close()
	}

	const selectFrontCode = () => {
		sgcodeOption.value = sgcodeOptionBak.value
		let array = tzArray.value.filter((e) => {
			return e.frontCode === tzObj.value.frontCode
		})
		tzObj.value.deviceCode = array[0].deviceCode

		sgcodeOption.value = sgcodeOption.value.filter((item) => {
			return tzObj.value.frontCode === item.frontCode
		})
	}

	const closeEdit = () => {
		editDialog.value.close()
	}

	/**
	 * 三个cameraList做匹配 并渲染表格
	 */
	const initTableData = () => {
		cameraTable.value = []
		//设备查询的摄像机直接加入表格

		for (let j = 0; j < cameraFromDeivce.value.length; j++) {
			let obj = {}
			obj.name = cameraFromDeivce.value[j].name
			obj.type = cameraFromDeivce.value[j].type
			obj.channel = cameraFromDeivce.value[j].channel
			obj.sgcode = cameraFromDeivce.value[j].sgcode
			obj.id = cameraFromDeivce.value[j].id
			obj.nvrid = cameraFromDeivce.value[j].nvrid
			cameraTable.value.push(obj)
		}

		for (let i = 0; i < cameraFromChannel.value.length; i++) {
			let find = cameraTable.value.find(function (item) {
				return item.channel === cameraFromChannel.value[i].channel;
			});
			if (find === undefined || find === null) {
			} else {
				find.user = cameraFromChannel.value[i].user
				find.pass = cameraFromChannel.value[i].pass
				find.state = cameraFromChannel.value[i].state
				find.ip = cameraFromChannel.value[i].ip
				find.rtspUrl = cameraFromChannel.value[i].rtspUrl
			}
		}

		loading.value = false
		uni.hideLoading();

	}

	const editCamera = (camera) => {
		editForm.value.ip = camera.ip
		editForm.value.channel = camera.channel
		editForm.value.sgcode = camera.sgcode
		editForm.value.type = camera.type
		editForm.value.name = camera.name
		editDialog.value.open()
	}

	/**
	 * 获取通道信息
	 */
	const getChannelInfo = () => {
		let params = {
			driver: "hiknet",
			ip: nvr.value.ip,
			port: station.value.videoData.videoPort,
			user: station.value.videoData.videoUsername,
			pass: station.value.videoData.videoPassword
		}
		return new Promise((resolve, reject) => {
			uni.request({
				url: WEB_URL + '/nvr?t=info',
				data: params,
				method: 'POST',
				header: {
					'Content-Type': 'application/json'
				},
				dataType: 'json',
				success: (res) => {
					cameraFromChannel.value = res.data
					console.log(res.data);
					resolve('suc');
				},
				complete: (complete) => {
					//statusCode:400 不往下走
					console.log(complete.statusCode)
				},
				fail(err) {
					console.log(err)
					uni.showModal({
						title: '提示',
						content: '获取通道信息失败，系统异常',
						confirmText: "确定",
						showCancel: false,
					})
					reject('err')
				}
			})
		})
	}

	/**
	 * 获取设备列表
	 */
	const getDeviveList = () => {
		return new Promise((resolve, reject) => {
			uni.request({
				url: WEB_URL + '/app/getVideoDevice',
				method: 'GET',
				success: (res) => {
					//取第一个NVR设备
					if (res.data.data.length > 0) {
						//获取cameras
						if (res.data.data[0].cameras != null) {
							cameraFromDeivce.value = res.data.data[0].cameras
						}
					}
					resolve('suc');
				},
				fail(err) {
					uni.showModal({
						title: '提示',
						content: '获取设备列表失败，系统异常',
						confirmText: "确定",
						showCancel: false,
					})
				}
			})
		})
	}

	/**
	 * 设备发现
	 */
	const find = () => {
		// uni.showLoading({
		// 	title: '数据加载中'
		// });
		return new Promise((resolve, reject) => {
			uni.request({
				url: WEB_URL + '/find?t=find&wait=3&reset=1',
				method: 'GET',
				success: (res) => {
					//返回一个数组
					if (res.data.length > 1) {
						//找到第一个NVR
						for (let i = 0; i < res.data.length; i++) {
							let flag = false
							if (res.data[i].majorType == 0) {
								if (flag == true) {
									continue
								}
								nvr.value = res.data[i]
								activated.value = res.data[i].activated
								// }
								if (nvr.value.ip === res.data[i].ip) {
									serial.value = res.data[i].serial
								}
								flag = true
							}
							//摄像机设备
							if (res.data[i].majorType == 1) {
								cameraFromFind.value.push(res.data[i])
							}
						}
					}
					resolve('suc');
				},
				fail(err) {
					console.log(err)
					reject('err')
				}
			})

		})

	}

	const excelToDataUrl = (file) => {
		return new Promise((resolve) => {
			// 对文件对象的处理
			var reader = new plus.io.FileReader();
			reader.readAsDataURL(file);
			reader.onload = function () {
				resolve(this.result);
			};
		});
	}

	const importExcel = () => {
		const filePicker = uni.requireNativePlugin('Ba-FilePicker')
		filePicker.selectFile({
			'selectType': 0,
			'maxCount': 1,
			'filetypes': 'xlsx,xls'
		}, (ret) => {
			if (ret.data) {
				//解析文件
				plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, fs => { //请求文件系统
					fs.root.getFile(
						ret.data[0].absolutePath, //请求文件的地址
						{
							create: false //当文件不存在时创建
						}, fileEntry => {
							fileEntry.file(function (file) {
								//new一个可以用来读取文件的对象fileReader
								let fileReader = new plus.io.FileReader();
								fileReader.readAsDataURL(file)
								fileReader.onerror = e => { //读文件失败
									console.log("获取文件失败", fileReader.error);
									plus.nativeUI.toast("获取文件失败,请重启应用", {
										background: "#ffa38c",
										duration: 2000
									});
									return;
								};

								fileReader.onload = e => { //读文件成功
									// console.log("读取excel成功");
									const model = /.*base64,/
									const newFile = e.target.result.replace(model, '');
									const workbook = XLSX.read(newFile, { type: 'base64' })
									// console.log('workbook', workbook);
									//excel解析
									getFileData(workbook.Sheets.sheet)
									plus.nativeUI.toast('导入成功', {
										background: "#ffa38c",
										duration: 2000
									})
								};
								fileReader.onloadend = e => {
									plus.nativeUI.toast('导入成功', {
										background: "#ffa38c",
										duration: 2000
									})
								}
							});
						}, error => {
							console.log("2新建获取文件失败", error);
							plus.nativeUI.toast("获取文件失败,请重启应用", {
								background: "#ffa38c",
								duration: 2000
							});
							return;
						});
				},
					e => {
						console.log("1请求文件系统失败", e.message);
						plus.nativeUI.toast("请求系统失败,请重启应用", {
							background: "#ffa38c",
							duration: 2000
						});
						return;
					}
				);
			}
		});
	}

	const getFileData = (sheet) => {
		codeOptions.value = []
		tzArray.value = []
		let cl = sheet["!ref"]
		let index = cl.indexOf(":");
		let max = parseInt(cl.substr(index + 2, cl.length))

		for (let i = 2; i <= max; i++) {
			let obj : any = {}
			for (let j = 1; j <= 22; j++) {
				if (j == 4) {
					obj.changjing = sheet["D" + i.toString()]["v"]
				}
				if (j == 5) {
					obj.syqd = sheet["E" + i.toString()]["v"]
				}
				if (j == 6) {
					obj.sbjc = sheet["F" + i.toString()]["v"]
				}
				if (j == 9) {
					obj.deviceCode = sheet["I" + i.toString()]["v"]

				}
				if (j == 21) {
					obj.frontCode = sheet["U" + i.toString()]["v"]
					const find = codeOptions.value.find(function (item) {
						return obj.frontCode === item.value
					})
					if (find === undefined) {
						codeOptions.value.push({ text: obj.syqd, value: obj.frontCode })
					}
					let sg = { text: obj.sbjc, value: obj.deviceCode, frontCode: obj.frontCode }
					sgcodeOption.value.push(sg)
					sgcodeOptionBak.value.push(sg)
				}
			}
			tzArray.value.push(obj)
		}
	}


	const save = () => {
		uni.showModal({
			title: '提示',
			content: '是否确认保存配置?',
			confirmText: "确定",
			cancelText: "取消",
			showCancel: true,
			success: (res) => {
				if (res.confirm) {
					if (tzObj.value.frontCode === '') {
						uni.showModal({
							title: '提示',
							content: '请选择前端编码',
							confirmText: "确定",
							showCancel: false,
						})
					} else {
						const videoInfo = uni.getStorageSync('videoData')
						let cameras = []
						for (let i = 0; i < cameraTable.value.length; i++) {
							let obj = {
								id: cameraTable.value[i].id,
								sgcode: cameraTable.value[i].sgcode
							}
							cameras.push(obj)
						}
						let data = {
							localcode: tzObj.value.frontCode,
							sipiotuser: tzObj.value.frontCode,
							sipiotip: platformData.value.platformVideoIP,
							sipiotport: parseInt(platformData.value.platformVideoPort),
							sipiotcode: platformData.value.platformVideoCode,
							sipiotpwd: platformData.value.platformVideoPassword,
							cameras: cameras
						}
						let params = { data: data }
						console.log('params', params);
						uni.request({
							url: WEB_URL + '/app/updateVideoDevice',
							data: params,
							method: 'POST',
							header: {
								'Content-Type': 'application/json'
							},
							dataType: 'json',
							success: async (res) => {
								if (res.data.code === 0) {
									uni.showToast({
										title: '上传配置成功',
										icon: 'success'
									})

									await getDeviveList()
									//2.默认调用一次设备发现
									await find()
									//4.初始化通道信息
									await getChannelInfo()
									initTableData()

								} else {
									uni.showModal({
										title: '提示',
										content: res.data.message,
										confirmText: "确定",
										showCancel: false,
									})
								}

							},
							fail: (err) => {
								uni.showModal({
									title: '提示',
									content: '上传失败，系统异常',
									confirmText: "确定",
									showCancel: false,
								})
							},
						})

					}
				}
			}
		})
	}

	const videoPreview = (camera) => {
		camera.nvrIp = nvr.value.ip
		camera.nvrPort = nvr.value.port
		camera.rtspUrl = nvr.value.rtspUrl
		camera.pageName = 'videoUpload'
		uni.navigateTo({
			url: `/pages/videoPreview/videoPreview?item=${encodeURIComponent(JSON.stringify(Object.assign(station.value, camera)))}`,
		})
	}

	// 多选
	const selectionChange = (e) => {
		selectedIndexs.value = e.detail.index
	}

	/**
	 * 点击设备发现
	 */
	const clickFind = async () => {
		await find()
	}


	const addCamera = async () => {
		const valid = await deviceForm.value.validate();
		if (valid) {
			//json序列化深拷贝
			let data = JSON.parse(JSON.stringify(formData));
			cameraTable.value.push(data)
			uni.showToast({
				title: '添加成功',
				icon: 'success'
			});
			inputDialog.value.close()
			formData.ip = ""
			formData.password = ""
			formData.user = ""
			formData.port = ""
		} else {
			//校验失败
		}
	}

	const close = () => {
		formData.ip = ""
		formData.password = ""
		formData.user = ""
		formData.port = ""
		inputDialog.value.close()
	}


	const gotoAddCamera = () => {
		inputDialog.value.open()
	}
	// const loading = ref(false)
</script>

<style>
	.flex-alin {
		display: flex;
		align-items: center;
	}

	/* 基本样式 */
	.video-device-form {
		padding: 45px 20px;
		background-color: #f7f7f7;
		/* border-radius: 8px; */
		height: 92vh;

	}

	.header {
		/* border: 1px solid red; */
		display: flex;
		justify-content: center;
		align-items: center;
		padding-bottom: 20px;
		position: relative;
	}

	.back-img {
		position: absolute;
		left: 0;
	}

	.header-title {
		font-size: 24px;
		color: #666;
	}

	.video-device-container {
		/* border: 1px solid red; */
		padding: 20px;
		background-color: #fff;
		box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
		border-radius: 5px;
	}

	.form-header {
		display: flex;
		justify-content: space-between;
		align-items: center;
	}

	.header-text {
		font-size: 24px;
		color: #666;
	}

	.header-tag {
		margin-left: 20px;
	}

	.header-btn {
		display: flex;
		justify-content: center;
		align-items: center;
		font-size: 16px;
		background-color: #48b0b1 !important;
		/* color: white; */
		padding: 0 20px;
		border-radius: 4px;
	}

	.icon-container {
		width: 20px;
		height: 20px;
		display: flex;
		justify-content: center;
		align-items: center;
		margin-right: 10px;
	}

	.icon {
		width: 100%;
		height: 100%;
	}

	.video-device-info {
		width: 100%;
		margin-top: 20px;
	}

	.form-row {
		/* margin-top: 20px; */
		display: flex;
		justify-content: space-between;
		/* margin: 10px 0; */
	}

	.form-row-last {
		display: grid;
		grid-template-columns: repeat(2, 1fr);
	}

	.info-item {
		flex: 1;
		margin-right: 10px;
		/* 为每个表单项添加右边距 */
	}



	/* 当前行只有最后一个输入框时，让它占一半 */
	.video-device-info>.last-item:last-child {
		flex: 1 1 calc(50% - 20px);
	}

	.label {
		font-size: 18px;
		color: #666;
		width: 120px;
		text-align: right;
		flex-shrink: 0;
		padding-right: 10px;
	}

	.input {
		padding: 8px;
		border: 1px solid #ddd;
		border-radius: 4px;
		font-size: 18px;

	}

	.video-device-list-container {
		margin-top: 20px;
		background-color: #fff;
		box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
		border-radius: 8px;
		padding: 20px;
	}

	.video-device-list-header {
		display: flex;
		justify-content: space-between;
		align-items: center;
		margin-bottom: 20px;
	}

	.video-device-list-title {
		font-size: 24px;
		color: #666;
	}

	.video-device-list-buttons {
		display: flex;
		gap: 10px;
	}

	.add-channel-btn,
	.add-camera-btn {
		display: flex;
		justify-content: center;
		align-items: center;
		border-radius: 4px;
		font-size: 16px;
	}

	.add-channel-btn {
		background-color: #48b0b1 !important;
	}

	.add-camera-btn {
		background-color: #07c160 !important;
	}

	.button-bar {
		/* position: fixed;
		bottom: 0;
		left: 0;
		right: 0; */

		display: flex;
		border-radius: 4px;
		font-size: 16px;
		padding: 20px;
		z-index: 1000;
	}

	.discover-btn {
		font-size: 16px;
		display: flex;
		justify-content: center;
		align-items: center;
		background-color: #5a79ff !important;
	}

	.import-btn {
		background-color: #48b0b1 !important;
	}

	.save-btn-video {
		font-size: 16px;
		display: flex;
		justify-content: center;
		align-items: center;
		background-color: #07c160 !important;
	}
</style>